﻿using System;

namespace DBUtil.Attributes
{
    #region Ignore
    [AttributeUsage(AttributeTargets.Property)]
    public class IgnoreUpdateAttribute : Attribute { }
    [AttributeUsage(AttributeTargets.Property)]
    public class IgnoreSelectAttribute : Attribute { }
    [AttributeUsage(AttributeTargets.Property)]
    public class IgnoreInsertAttribute : Attribute { }
    [AttributeUsage(AttributeTargets.Property)]
    public class IgnoreWriteAttribute : Attribute { }
    #endregion

    #region PrimaryKey
    [AttributeUsage(AttributeTargets.Property)]
    public class PrimaryKeyAttribute : Attribute
    {
        /// <summary>
        /// 主键生成策略,默认: 自定义
        /// </summary>
        public KeyStrategy KeyStrategy { get; set; } = KeyStrategy.Custom;
    }

    public enum KeyStrategy
    {
        /// <summary>
        /// 自定义，插入时必须手动指定值，默认
        /// </summary>
        Custom,
        /// <summary>
        /// 自增
        /// <list type="number">
        /// <item>sqlserver：identity(1,1)</item>
        /// <item>mysql：auto_increment</item>
        /// </list>
        /// </summary>
        Identity
    }
    #endregion

    #region JsonStore
    /// <summary>
    /// 表示将此列实际存储为json格式, 使用示例: [JsonStore(Bucket="ext",Key="DetailName",SelectKey="name")]
    /// <list type="bullet">
    /// <item>Bucket(必填): json列名, 如: create table test(ext json), 那么可以有 [JsonStore(Bucket="ext")]</item>
    /// <item>Key(非必填): json下级属性名, 如: [JsonStore(Bucket="ext",Key="DetailName")]</item>
    /// <item>SelectKey(非必填): 用于虚列, 如: create table test(ext json, name varchar(50) generated always as (ext->>'$.DetailName')), 此时可以有配置:
    /// <code>
    /// public class Person
    /// {
    ///     [JsonStore(Bucket="ext", Key="DetailName", SelectKey="name")]
    ///     public string Name { get;set; }
    /// }
    /// </code>
    /// 这样生成的sql可以是:
    /// <code>select t.name from test t</code>
    /// 而不必是:
    /// <code>select json_value(t.ext,'$.DetailName' returning char) from test t</code>
    /// </item>
    /// </list>
    /// </summary>
    /// <remarks>
    /// 注意: 如果有特殊字符
    /// <list type="bullet">
    /// <item>
    /// [JsonStore] 中的 <c>Bucket</c>、<c>SelectKey</c> 和 [Table]、[Column] 中表现一致(需要自行处理其中的特殊符号), 如:
    /// <list type="bullet">
    /// <item>以数字开头或含有空格: [JsonStore(Bucket="\"123 ok\"")</item>
    /// <item>含有单引号,双引号,甚至换行符: [JsonStore(Bucket="\"p'\\"\\r\\np\"")</item>
    /// </list>
    /// </item>
    /// <item>
    /// [JsonStore] 中的 <c>Key</c> 特殊(不需要自行处理其中的特殊符号), 如:
    /// <list type="bullet">
    /// <item>以数字开头或含有空格: [JsonStore(Bucket="...",Key="123 ok")</item>
    /// <item>含有单引号,双引号,甚至换行符: [JsonStore(Bucket="...",Key="p'\"\r\np")</item>
    /// </list>
    /// </item>
    /// </list>
    /// </remarks>
    [AttributeUsage(AttributeTargets.Property)]
    public class JsonStoreAttribute : Attribute
    {
        /// <summary>
        /// 实际列名,必须填写,比如: "properties" create table t_user(id int primary key,properties json)
        /// </summary>
        /// <remarks>
        /// 注意: 这里的 Bucket 配置和 [Column()] [Table()] 的配置一样, 使用的时候可以直接拼接, 所以如果有特殊字符请使用者自行处理, 如:
        /// <list type="bullet">
        /// <item>以数字开头或含有空格: [JsonStore(Bucket="123 ok")</item>
        /// <item>含有单引号,双引号,甚至换行符: [JsonStore(Bucket="p'\"\r\np")</item>
        /// </list>
        /// </remarks>
        public string Bucket { get; set; }
        /// <summary>
        /// 一般使用如: [JsonStore(Bucket="...",Key="name"}), 当有特殊字符时如下:
        /// <list type="bullet">
        /// <item>以数字开头, 含有空格: [JsonStore(Bucket="...",Key="123 ok"}</item>
        /// <item>含有单引号,双引号,甚至换行符: [JsonStore(Bucket="...",Key="p'\"\r\np"}</item>
        /// </list>
        /// <br/>
        /// 另外解释下, 这个属性为什么不能像 [Column("name")] 中的 name 一样直接使用？
        /// <list type="number">
        /// <item>
        /// [Column("name")] 中的 name 是可以直接放在sql对象(select t.name from ...)和jsonpath('$.name')中的, 转义的工作交给使用者可以让其有更多的控制权;
        /// </item>
        /// <item>
        /// 对于[JsonStore(Bucket="...",Key="name")] 中的 name, 有三个应用场景(第二个场景要求必须配置的是没转义的,否则就必须反转义):
        /// <list type="number">
        /// <item> json_object("name","...") </item>
        /// <item> JsonObject.SetFluent("name","...") </item>
        /// <item> '$.name' </item>
        /// </list>
        /// </item>
        /// </list>
        /// </summary>
        /// <remarks>注意: 这个属性在使用时会先进行转义, <seealso cref="DBAccess.EscapeString(string)"/> , 这一点不同于 [Column("colname")] 中的列名,以及 [JsonStore(Bucket="colname")] 中的列名</remarks>
        public string Key { get; set; }
        /// <summary>
        /// 为了优化性能(如: generate always as ...), 查询时使用此列进行查询<br/>
        /// 如: [JsonStore(Bucke="ext",Key="name",SelectKey="namesel")]<br/>
        /// 查询时: select t.namesel from test t<br/>
        /// 而不是: select json_value(t.ext,'$.name') from test t<br/>
        /// </summary>
        /// <remarks>
        /// 注意: 在插入/更新时不起作用<br/>
        /// </remarks>
        public string SelectKey { get; set; }
    }
    #endregion
}